package com.ngis.model.mdl;

import java.util.ArrayList;

import org.dom4j.Element;

public class ModelRuntime {
	
	public ModelRuntime()
	{
		mHardwareRequirementList = new ArrayList<HardwareRequirement>();
		mSoftwareRequirementList = new ArrayList<SoftwareRequirement>();
		mModelAssemblyList = new ArrayList<ModelAssembly>();
		mSupportiveResourceList = new ArrayList<SupportiveResource>();
	}
	public boolean loadFromXml(Element pModelClassElement) {
		Element runtimeEle = pModelClassElement.element("Runtime");
		mName = runtimeEle.attributeValue("name");
		mVersion = runtimeEle.attributeValue("version");
		mBaseDirectory = runtimeEle.attributeValue("baseDir");
		mEntry = runtimeEle.attributeValue("entry");

		Element hardwareConfigures = runtimeEle.element("HardwareConfigures");
		Element softwareConfigures = runtimeEle.element("SoftwareConfigures");
		Element modelAssemblyConfigures = runtimeEle.element("Assemblies");
		Element supportiveConfigures = runtimeEle
				.element("SupportiveResources");

		int count = 0;
		if (hardwareConfigures!=null)
			count = hardwareConfigures.elements().size();
		for (int iHard = 0; iHard < count; iHard++) {
			Element childEle = (Element) hardwareConfigures.elements().get(iHard);
			HardwareRequirement temp_requirement = new HardwareRequirement();
			temp_requirement.requirementKey = childEle.attributeValue("key");
			temp_requirement.requirementValue = childEle
					.attributeValue("value");
			mHardwareRequirementList.add(temp_requirement);
		}

		count = 0;
		if (softwareConfigures!=null)
			count = softwareConfigures.elements().size();
		for (int iSoft = 0; iSoft < count; iSoft++) {
			Element childEle = (Element) softwareConfigures.elements().get(iSoft);
			SoftwareRequirement temp_requirement = new SoftwareRequirement();
			temp_requirement.requirementKey = childEle.attributeValue("key");
			temp_requirement.requirementValue = childEle.attributeValue("value");
			temp_requirement.requirementPlatform = childEle.attributeValue("platform");
			mSoftwareRequirementList.add(temp_requirement);
		}

		count = 0;
		if (modelAssemblyConfigures!=null)
			count = modelAssemblyConfigures.elements().size();
		for (int iAss = 0; iAss < count; iAss++) {
			Element childEle = (Element) modelAssemblyConfigures.elements().get(iAss);
			ModelAssembly temp_requirement = new ModelAssembly();
			temp_requirement.assemblyName = childEle.attributeValue("name");
			temp_requirement.assemblyPath = childEle.attributeValue("path");
			mModelAssemblyList.add(temp_requirement);
		}

		count = 0;
		if (supportiveConfigures!=null)
			count = supportiveConfigures.elements().size();
		for (int iSupport = 0; iSupport < count; iSupport++) {
			Element childEle = (Element) supportiveConfigures.elements().get(iSupport);
			SupportiveResource temp_requirement = new SupportiveResource();
			temp_requirement.resourceType = childEle.attributeValue("type");
			temp_requirement.resourceName = childEle.attributeValue("name");
			mSupportiveResourceList.add(temp_requirement);
		}

		return true;
	}

	boolean formatToXml(Element pModelClassElement) {
		Element runtimeEle = pModelClassElement.addElement("Runtime");
		runtimeEle.addAttribute("name", mName);
		runtimeEle.addAttribute("version", mVersion);
		runtimeEle.addAttribute("baseDir", mBaseDirectory);
		runtimeEle.addAttribute("entry", mEntry);

		Element hardwareConfigures = runtimeEle
				.addElement("HardwareConfigures");
		Element softwareConfigures = runtimeEle
				.addElement("SoftwareConfigures");
		Element modelAssemblyConfigures = runtimeEle.addElement("Assemblies");
		Element supportiveConfigures = runtimeEle
				.addElement("SupportiveResources");

		for (int i = 0; i < mHardwareRequirementList.size(); i++) {
			Element temp_ele = hardwareConfigures.addElement("Add");
			temp_ele.addAttribute("key",
					mHardwareRequirementList.get(i).requirementKey);
			temp_ele.addAttribute("value",
					mHardwareRequirementList.get(i).requirementValue);
		}

		for (int i = 0; i < mSoftwareRequirementList.size(); i++) {
			Element temp_ele = softwareConfigures.addElement("Add");
			temp_ele.addAttribute("key",
					mSoftwareRequirementList.get(i).requirementKey);
			temp_ele.addAttribute("value",
					mSoftwareRequirementList.get(i).requirementValue);
			temp_ele.addAttribute("platform",
					mSoftwareRequirementList.get(i).requirementPlatform);
		}

		for (int i = 0; i < mModelAssemblyList.size(); i++) {
			Element temp_ele = modelAssemblyConfigures.addElement("Assembly");
			temp_ele.addAttribute("name",
					mModelAssemblyList.get(i).assemblyName);
			temp_ele.addAttribute("path",
					mModelAssemblyList.get(i).assemblyPath);
		}

		for (int i = 0; i < mSupportiveResourceList.size(); i++) {
			Element temp_ele = supportiveConfigures.addElement("Add");
			temp_ele.addAttribute("type",
					mSupportiveResourceList.get(i).resourceType);
			temp_ele.addAttribute("name",
					mSupportiveResourceList.get(i).resourceName);
		}
		return true;
	}

	public String getName() {
		return mName;
	}

	public void setName(String pName) {
		mName = pName;
	}

	public String getVersion() {
		return mVersion;
	}

	public void setVersion(String pVersion) {
		mVersion = pVersion;
	}

	public String getEntry() {
		return mEntry;
	}

	public void setEntry(String pEntry) {
		mEntry = pEntry;
	}

	public String getBaseDirectory() {
		return mBaseDirectory;
	}

	public void setBaseDirectory(String pDirectory) {
		mBaseDirectory = pDirectory;
	}

	// ////////////////////////////////////////////////////////////////////////
	public boolean addHardwareRequirement(HardwareRequirement pRequirement) {
		for (int i = 0; i < mHardwareRequirementList.size(); i++) {
			if (mHardwareRequirementList.get(i).requirementKey.equals(pRequirement.requirementKey)
					&& mHardwareRequirementList.get(i).requirementValue.equals(pRequirement.requirementValue)) {
				return false;
			}
		}
		mHardwareRequirementList.add(pRequirement);
		return true;
	}

	public boolean addSoftwareRequirement(SoftwareRequirement pRequirement) {
		for (int i = 0; i < mSoftwareRequirementList.size(); i++) {
			if (mSoftwareRequirementList.get(i).requirementKey.equals(pRequirement.requirementKey)
					&& mSoftwareRequirementList.get(i).requirementValue.equals(pRequirement.requirementValue)) {
				return false;
			}
		}
		mSoftwareRequirementList.add(pRequirement);
		return true;
	}

	public boolean addModelAssembly(ModelAssembly pRequirement) {
		for (int i = 0; i < mModelAssemblyList.size(); i++) {
			if (mModelAssemblyList.get(i).assemblyName.equals(pRequirement.assemblyName)
					&& mModelAssemblyList.get(i).assemblyPath.equals(pRequirement.assemblyPath)) {
				return false;
			}
		}
		mModelAssemblyList.add(pRequirement);
		return true;
	}

	public boolean addSupportiveResource(SupportiveResource pRequirement) {
		for (int i = 0; i < mSupportiveResourceList.size(); i++) {
			if (mSupportiveResourceList.get(i).resourceType.equals(pRequirement.resourceType)
					&& mSupportiveResourceList.get(i).resourceName.equals(pRequirement.resourceName)) {
				return false;
			}
		}
		mSupportiveResourceList.add(pRequirement);
		return true;
	}

	// ////////////////////////////////////////////////////////////////////////
	public int getHardwareRequirementCount() {
		return mHardwareRequirementList.size();
	}

	public int getSoftwareRequirementCount() {
		return mSoftwareRequirementList.size();
	}

	public int getModelAssemblyCount() {
		return mModelAssemblyList.size();
	}

	public int getSupportiveResourceCount() {
		return mSupportiveResourceList.size();
	}

	public HardwareRequirement getHardwareRequirement(int idx) {
		if (idx < 0 || idx >= mHardwareRequirementList.size())
			return null;
		HardwareRequirement pRequirement = mHardwareRequirementList.get(idx);
		return pRequirement;
	}

	public SoftwareRequirement getSoftwareRequirement(int idx) {
		if (idx < 0 || idx >= mSoftwareRequirementList.size())
			return null;
		SoftwareRequirement pRequirement = mSoftwareRequirementList.get(idx);
		return pRequirement;
	}

	public ModelAssembly getModelAssembly(int idx) {
		if (idx < 0 || idx >= mModelAssemblyList.size())
			return null;
		ModelAssembly pRequirement = mModelAssemblyList.get(idx);
		return pRequirement;
	}

	public SupportiveResource getSupportiveResource(int idx) {
		if (idx < 0 || idx >= mSupportiveResourceList.size())
			return null;
		SupportiveResource pRequirement = mSupportiveResourceList.get(idx);
		return pRequirement;
	}

	// ////////////////////////////////////////////////////////////////////////
	public boolean removeHardwareRequirement(HardwareRequirement pRequirement) {
		if (mHardwareRequirementList.contains(pRequirement)) {
			mHardwareRequirementList.remove(pRequirement);
			return true;
		}
		return false;
	}

	public boolean removeSoftwareRequirement(SoftwareRequirement pRequirement) {
		if (mSoftwareRequirementList.contains(pRequirement)) {
			mSoftwareRequirementList.remove(pRequirement);
			return true;
		}
		return false;
	}

	public boolean removeModelAssembly(ModelAssembly pRequirement) {
		if (mModelAssemblyList.contains(pRequirement)) {
			mModelAssemblyList.remove(pRequirement);
			return true;
		}
		return false;
	}

	public boolean removeSupportiveResource(SupportiveResource pRequirement) {
		if (mSupportiveResourceList.contains(pRequirement)) {
			mSupportiveResourceList.remove(pRequirement);
			return true;
		}
		return false;
	}

	public boolean removeHardwareRequirement(int idx) {
		if (idx < 0 || idx >= mHardwareRequirementList.size())
			return false;
		mHardwareRequirementList.remove(idx);
		return true;
	}

	public boolean removeSoftwareRequirement(int idx) {
		if (idx < 0 || idx >= mSoftwareRequirementList.size())
			return false;
		mSoftwareRequirementList.remove(idx);
		return true;
	}

	public boolean removeModelAssembly(int idx) {
		if (idx < 0 || idx >= mModelAssemblyList.size())
			return false;
		mModelAssemblyList.remove(idx);
		return true;
	}

	public boolean removeSupportiveResource(int idx) {
		if (idx < 0 || idx >= mSupportiveResourceList.size())
			return false;
		mSupportiveResourceList.remove(idx);
		return true;
	}

	public boolean compareOther(ModelRuntime pRuntime, CompareFlag compareFlag) {
		if (mName.equals(pRuntime.getName()) == false) {
			compareFlag.Obj = "Runtime";
			compareFlag.Name = "name";
			return false;
		}
		if (mVersion.equals(pRuntime.getVersion()) == false) {
			compareFlag.Obj = "Runtime";
			compareFlag.Name = "version";
			return false;
		}
		if (mEntry.equals(pRuntime.getEntry()) == false) {
			compareFlag.Obj = "Runtime";
			compareFlag.Name = "entry";
			return false;
		}
		if (mBaseDirectory.equals(pRuntime.getBaseDirectory()) == false) {
			compareFlag.Obj = "Runtime";
			compareFlag.Name = "baseDir";
			return false;
		}

		if (mHardwareRequirementList.size() != pRuntime
				.getHardwareRequirementCount()) {
			compareFlag.Obj = "HardwareConfigures";
			compareFlag.Name = "HardwareRequirementCount";
			return false;
		}
		for (int i = 0; i < mHardwareRequirementList.size(); i++) {
			HardwareRequirement temp_req1 = mHardwareRequirementList.get(i);
			HardwareRequirement temp_req2 = pRuntime.getHardwareRequirement(i);
			if (temp_req1.compareOther(temp_req2) == false) {
				compareFlag.Obj = "Hardware";
				compareFlag.Name = temp_req1.requirementKey + "<-->"
						+ temp_req2.requirementKey;
				return false;
			}
		}
		if (mSoftwareRequirementList.size() != pRuntime
				.getSoftwareRequirementCount()) {
			compareFlag.Obj = "SoftwareConfigures";
			compareFlag.Name = "SoftwareRequirementCount";
			return false;
		}
		for (int i = 0; i < mSoftwareRequirementList.size(); i++) {
			SoftwareRequirement temp_req1 = mSoftwareRequirementList.get(i);
			SoftwareRequirement temp_req2 = pRuntime.getSoftwareRequirement(i);
			if (temp_req1.compareOther(temp_req2) == false) {
				compareFlag.Obj = "Software";
				compareFlag.Name = temp_req1.requirementKey + "<-->"
						+ temp_req2.requirementKey;
				return false;
			}
		}
		if (mModelAssemblyList.size() != pRuntime.getModelAssemblyCount()) {
			compareFlag.Obj = "Assemblies";
			compareFlag.Name = "AssemblyCount";
			return false;
		}
		for (int i = 0; i < mModelAssemblyList.size(); i++) {
			ModelAssembly temp_assembly1 = mModelAssemblyList.get(i);
			ModelAssembly temp_assembly2 = pRuntime.getModelAssembly(i);
			if (temp_assembly1.compareOther(temp_assembly2) == false) {
				compareFlag.Obj = "Assembly";
				compareFlag.Name = temp_assembly1.assemblyName + "<-->"
						+ temp_assembly2.assemblyName;
				return false;
			}
		}
		if (mSupportiveResourceList.size() != pRuntime
				.getSupportiveResourceCount()) {
			compareFlag.Obj = "SupportiveResources";
			compareFlag.Name = "SupportiveResourceCount";
			return false;
		}
		for (int i = 0; i < mSupportiveResourceList.size(); i++) {
			SupportiveResource temp_res1 = mSupportiveResourceList.get(i);
			SupportiveResource temp_res2 = pRuntime.getSupportiveResource(i);
			if (temp_res1.compareOther(temp_res2) == false) {
				compareFlag.Obj = "SupportiveResource";
				compareFlag.Name = temp_res1.resourceName + "<-->" + temp_res2.resourceName;
				return false;
			}
		}
		return true;
	}

	private String mName;
	private String mVersion;
	private String mEntry;
	private String mBaseDirectory;

	private ArrayList<HardwareRequirement> mHardwareRequirementList;
	private ArrayList<SoftwareRequirement> mSoftwareRequirementList;
	private ArrayList<ModelAssembly> mModelAssemblyList;
	private ArrayList<SupportiveResource> mSupportiveResourceList;
}
